package request

import (
	models2 "appService/src/application/admin/admin/adminModels"
	"appService/src/application/app/appModels"
	"appService/src/authValid"
	"appService/src/authValid/dataAuth"
	"appService/src/authValid/defaultB"
	"appService/src/authValid/userMap"
	"appService/src/global"
	"appService/src/libs/httpResult"
	"appService/src/libs/token"
	"appService/src/libs/utils"
	"appService/src/orm"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/util/guid"
	"net"
	"strings"
	"time"
	"xorm.io/builder"
)

type WsRequest struct {
	Request   *ghttp.Request
	Ws        *ghttp.WebSocket
	LoginUser *appModels.UserInfo // 当前登陆账号
	AuthCode  string              //当前访问的路由
}

//Init 执行对象收到请求时的初始化方法，在服务接口调用之前被回调执行
func (this *WsRequest) Init(r *ghttp.Request, ws *ghttp.WebSocket) {
	this.Request = r
	this.Ws = ws
	//初始化变量
	this.LoginUser = new(appModels.UserInfo)
	// 角色权限验证。
	this.RolesAuthCheck(true)
}

//RolesAuthCheck 角色权限验证。
func (this *WsRequest) RolesAuthCheck(isParams bool) {
	//设置当前访问的路由的权限标识
	this.AuthCode = utils.RouteToAuthCode(this.Request.Router.Uri, this.Request.Router.Method)
	// 判断路由是否需要登录
	apiRoute := authValid.AuthCodeGetRoute(this.AuthCode)
	// 当前 api 是否需要验证签名
	if apiRoute == nil || apiRoute.Id == "" {
		g.Log().Errorf("数据接口不存在")
		this.SendError("您访问的数据不存在")
	} else {
		if apiRoute.Visit > dataAuth.PUBLIC {
			//登陆 验证token权限
			this.ValidToken(false)
			// 判断访问权限
			if apiRoute.Visit > dataAuth.LOGIN {
				// 判断是否有访问权限
				if !authValid.UserIsToAuthCode(apiRoute, this.AuthCode, this.LoginUser) {
					this.SendNoAuth("您没有 o(╥﹏╥)o┣ %v ┨ 的操作权限，请联系管理员。", apiRoute.Title)
				}
			}
		}
	}

	//设置当前请求的【部门机构】
	this.SetBranch()
}
func (this *WsRequest) CloseWs() {
	_ = this.Ws.Close()
}

//ValidToken Authorization token
//ValidToken 验证token令牌 isReturn为真，会返回 true/false, 为假，只会在验证成功的时候返回真
func (this *WsRequest) ValidToken(isReturn bool) bool {
	tokenStr := this.Request.Cookie.Get("Authorization", "")
	if tokenStr == "" {
		tokenStr = this.Request.Header.Get("Authorization")
	}
	if tokenStr == "" {
		_, msgByte, err := this.Ws.ReadMessage()
		if err != nil {
			this.SendLogin("登陆验证失败，请重新登陆")
			this.CloseWs()
		}
		tokenStr = string(msgByte)
	}
	if tokenStr == "" {
		if isReturn {
			return false
		} else {
			this.SendLogin("您还没有登录，请登录")
		}
	}
	//验证token权限
	ok, err := token.CheckToken(tokenStr, func(uid string, userAccount string, loginStr string) {
		if userMap.Exist(uid) {
			this.LoginUser = userMap.Get(uid)
		} else {
			user := new(appModels.Users)
			ok, err := orm.Db.Where(builder.Eq{"uid": uid}).Get(user)
			if err != nil {
				g.Log().Errorf("token验证 —> 查询用户信息错误：%v", err)
				if !isReturn {
					this.SendError("权限验证失败")
				}
			}
			if !ok {
				userMap.Remove(uid)
				g.Log().Errorf("token验证 —> 用户【UID=%v】不存在", uid)
				if !isReturn {
					this.SendReLogin("您的令牌已失效，请重新登录")
				}
			}
			account := new(appModels.Account)
			db := orm.Db.Where(builder.Eq{"account": userAccount, "id": user.AccountId})
			ok, err = db.Get(account)
			if err != nil {
				g.Log().Errorf("token验证 —> 查询用户账号信息错误：%v", err)
				if !isReturn {
					this.SendError("权限验证失败")
				}
			}
			if !ok {
				userMap.Remove(uid)
				if !isReturn {
					this.SendReLogin("您的令牌已失效，请重新登录")
				}
			}
			branch, err := this.GetDefaultBranch()
			if err != nil {
				g.Log().Errorf("token验证 —> 获取默认部门机构，错误：%v", err)
				if !isReturn {
					this.SendError("权限验证失败")
				}
			}
			this.LoginUser.Account = *account
			this.LoginUser.User = *user
			this.LoginUser.DefaultBranchId = branch.Id
			branchIds := authValid.GetBranchIDs(this.LoginUser, true)
			this.LoginUser.BranchIds = *branchIds
		}
		if global.SingleLogin {
			if loginStr != this.LoginUser.User.LoginRand {
				userMap.Remove(this.LoginUser.User.Uid)
				if !isReturn {
					this.SendReLogin("您的令牌已失效，请重新登录")
				}
			}
		}
		this.LoginUser.User.LoginTime = time.Now()
		this.LoginUser.IsLogin = true
		userMap.Set(this.LoginUser)
	})
	if err != nil {
		if isReturn {
			return false
		} else {
			this.SendErrorf("%v", err)
		}
	}
	if !ok {
		if isReturn {
			return false
		} else {
			this.SendReLogin("您的令牌已失效，请重新登录")
		}
	}
	return true
}

//SetBranch 如果当前登陆账号没有所属【部门机构】，就设置为默认的
func (this *WsRequest) SetBranch() {
	if this.LoginUser.Account.Bid == "" || this.LoginUser.Account.Bid == "0" {
		branch, err := this.GetDefaultBranch()
		if err == nil {
			this.LoginUser.Account.Bid = branch.Id
		} else {
			this.SendError("权限验证失败")
		}
	}
}

//GetDefaultBranch 获取默认【部门机构】
func (this *WsRequest) GetDefaultBranch() (*models2.Branch, error) {
	if defaultB.DefaultBranch.Id == "" {
		branch := new(models2.Branch)
		has, err := orm.Db.Where(builder.Eq{"is_default": 1}).Get(branch)
		if err != nil {
			g.Log().Errorf("GetDefaultBranch：—> 获取默认【部门机构】信息，错误：%v", err)
			return nil, err
		}
		if has {
			defaultB.DefaultBranch = *branch
			return branch, nil
		} else {
			return nil, errors.New("GetDefaultBranch：—> 默认【部门机构】不存在")
		}
	} else {
		return &defaultB.DefaultBranch, nil
	}
}

//Guid 获取一个GUID
func (this *WsRequest) Guid() string {
	var (
		address = this.Request.RemoteAddr
		header  = fmt.Sprintf("%v", this.Request.Header)
	)
	return guid.S([]byte(address), []byte(header))
}

//GetProxyClientIp 获取 访问客户端(反向代理) IP
func (this *WsRequest) GetProxyClientIp() string {
	xForwardedFor := this.Request.Request.Header.Get("X-Forwarded-For")
	ip := strings.TrimSpace(strings.Split(xForwardedFor, ",")[0])
	if ip != "" {
		return ip
	}
	ip = strings.TrimSpace(this.Request.Request.Header.Get("X-Real-Ip"))
	if ip != "" {
		return ip
	}
	if ip, _, err := net.SplitHostPort(strings.TrimSpace(this.Request.Request.RemoteAddr)); err == nil {
		return ip
	}
	return ""
}

//Send 标准返回结果数据结构封装。
func (this *WsRequest) Send(code int, message string, data ...interface{}) {
	responseData := interface{}(nil)
	dataLen := len(data)
	if dataLen > 0 {
		if dataLen > 1 {
			responseData = data
		} else {
			responseData = data[0]
		}
	}
	ret := httpResult.JsonData{
		Code:    code,
		Message: message,
		Data:    responseData,
	}
	retByte, err := json.Marshal(ret)
	if err != nil {
		g.Log().Printf("【wsRequest】对象转json字符串数据，错误：%v", err)
		return
	}
	err = this.Ws.WriteMessage(1, retByte)
	if err != nil {
		g.Log().Printf("【wsRequest】发送Json字符串数据，错误：%v", err)
	}
}

//SendSuccess 成功 返回JSON数据
func (this *WsRequest) SendSuccess(msg string, data ...interface{}) {
	this.Send(httpResult.SUCCESS, msg, data...)
}

//SendSuccessData 成功 返回JSON数据 没有 msg
func (this *WsRequest) SendSuccessData(data ...interface{}) {
	this.Send(httpResult.SUCCESS, "", data...)
}

//SendError 错误 返回JSON数据
func (this *WsRequest) SendError(msg string, data ...interface{}) {
	this.Send(httpResult.ERROR, msg, data...)
}

//SendErrorf 错误 返回JSON数据
func (this *WsRequest) SendErrorf(msg string, params ...interface{}) {
	this.Send(httpResult.ERROR, fmt.Sprintf(msg, params...), nil)
}

//SendLogin 请登陆 返回JSON数据
func (this *WsRequest) SendLogin(msg string, data ...interface{}) {
	this.Send(httpResult.LOGIN, msg, data...)
}

//SendReLogin 登录过期，请重新登录 返回JSON数据
func (this *WsRequest) SendReLogin(msg string, data ...interface{}) {
	this.Send(httpResult.RELOGIN, msg, data...)
}

//SendNoAuth 没有访问权限 返回JSON数据
func (this *WsRequest) SendNoAuth(msg string, data ...interface{}) {
	this.Send(httpResult.NOAUTH, msg, data...)
}

//SendNoAuthf 没有访问权限 返回JSON数据
func (this *WsRequest) SendNoAuthf(msg string, params ...interface{}) {
	this.Send(httpResult.NOAUTH, fmt.Sprintf(msg, params...), nil)
}
